<template>
  <div class="app-container">
    <!-- 把所有字段都生成了，先删除不要的字段，再做定制化 -->
    <el-form :model="queryParams" ref="queryForm" v-show="showSearch" :inline="true" label-width="120px">
      <el-row>
        <el-col :span="5">
          <el-form-item label="数据源" prop="datasourceId">
            <dict-selector v-model="queryParams.datasourceId" :dictData="datasourceReadOptions" placeholder="请选择数据源" size="default" style="width: 240px;" />
          </el-form-item>
        </el-col>
        <el-col :span="5">
          <el-form-item label="数据集名称" prop="datasetNameLike">
            <el-input
              v-model="queryParams.datasetNameLike" placeholder="请输入数据集名称" clearable size="default" style="width: 240px"
              @keyup.enter="handleQuery" />
          </el-form-item>
        </el-col>
        <el-col :span="5">
          <el-form-item label="数据表名" prop="tableNameLike">
            <el-input v-model="queryParams.tableNameLike" placeholder="请输入数据表名" clearable size="default" style="width: 240px" @keyup.enter="handleQuery" />
          </el-form-item>
        </el-col>
        <el-col :span="5">
          <el-form-item label="是否启用" prop="isEnable">
            <el-radio-group v-model="queryParams.isEnable">
              <el-radio key="" label="">全部</el-radio>
              <el-radio v-for="dict in isEnableOptions" :key="dict.dictValue" :label="dict.dictValue">{{ dict.dictLabel }}</el-radio>
            </el-radio-group>
          </el-form-item>
        </el-col>
        <el-col :span="4">
          <el-form-item>
            <search-button @click="handleQuery" :perm="['data:dataset:search']" />
            <reset-button @click="resetQuery" :perm="['data:dataset:search']" />
          </el-form-item>
        </el-col>
      </el-row>
    </el-form>

    <el-row :gutter="10" class="mb8">
      <add-button @click="handleAdd" text="新增" :perm="['data:dataset:insert']" :roleType="['app']" />
      <delete-button @click="handleDelete" :disabled="multiple" :perm="['data:dataset:delete']" :roleType="['app']" />
      <right-toolbar v-model:showSearch="showSearch" @query-table="getList" :perm="['data:dataset:search']" />
    </el-row>

    <!-- 把所有字段都生成了，先删除不要的字段，再做定制化 -->
    <el-table v-loading="loading" :data="dataList" @selection-change="handleSelectionChange">
      <el-table-column type="selection" width="55" align="center" />
      <el-table-column label="数据源" prop="datasourceId" :show-overflow-tooltip="true" min-width="100">
        <template #default="scope">
          {{ selectDictLabel(datasourceReadOptions,scope.row.datasourceId) }}
        </template>
      </el-table-column>
      <el-table-column label="数据集名称" prop="datasetName" :show-overflow-tooltip="true" min-width="100" />
      <el-table-column label="SQL模式" prop="sqlMode" width="100" align="center">
        <template #default="scope">
          <yes-no-tag :value="scope.row.sqlMode" />
        </template>
      </el-table-column>
      <el-table-column label="数据表名" prop="tableName" :show-overflow-tooltip="true" min-width="100" />
      <el-table-column label="表字段名" prop="columnName" :show-overflow-tooltip="true" min-width="100" />
      <el-table-column label="过滤条件" prop="filterWhere" :show-overflow-tooltip="true" min-width="100" />
      <el-table-column label="查询SQL" prop="selectSql" :show-overflow-tooltip="true" min-width="100" />
      <el-table-column label="是否启用" prop="isEnable" align="center" width="100">
        <template #default="scope">
          <yes-no-tag yesText="启用" noText="禁用" :value="scope.row.isEnable" />
        </template>
      </el-table-column>
      <el-table-column label="更新人" prop="updateBy" align="center" width="120" />
      <el-table-column label="更新时间" prop="updateTime" align="center" width="160" />
      <el-table-column label="操作" align="center" width="120" class-name="small-padding fixed-width" v-if="hasRoleType(['app'])">
        <template #default="scope">
          <text-edit-button @click="handleUpdate(scope.row)" :perm="['data:dataset:update']" :roleType="['app']" />
          <text-delete-button
            @click="handleDelete(scope.row)" :perm="['data:dataset:delete']" :roleType="['app']"
            :title="'是否确认删除记录'+scope.row.datasetId+'?'" />
        </template>
      </el-table-column>
    </el-table>
    <pagination v-show="total>0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />

    <!-- 添加或修改对话框 -->
    <el-dialog v-el-drag-dialog :title="title" :close-on-click-modal="false" v-model="open" width="800px" append-to-body>
      <el-form ref="form" :model="form" :rules="rules" label-width="120px">
        <el-row :gutter="20">
          <el-col :span="24">
            <el-form-item label="数据集名称" prop="datasetName">
              <el-input v-model="form.datasetName" placeholder="请输入数据集名称" clearable />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="24">
            <el-form-item label="数据源" prop="datasourceId">
              <dict-selector v-model="form.datasourceId" :dictData="datasourceReadOptions" placeholder="请选择数据源" clearable @change="datasourceChange" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="24">
            <el-form-item label="构建模式" prop="sqlMode">
              <el-switch v-model="form.sqlMode" active-value="Y" active-text="SQL模式" inactive-text="表模式" inactive-value="N" @change="concatSql">
              </el-switch>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20" v-if="form.sqlMode!=='Y'">
          <el-col :span="24">
            <el-form-item label="From表" prop="tableName">
              <el-select v-model="form.tableName" @change="tableNameChange" filterable placeholder="输入关键词过滤" style="width:100%;">
                <el-option
                  v-for="dict in tableNameOptions" :key="dict.dictValue" :label="dict.dictValue + (dict.dictLabel?('('+dict.dictLabel+')'):'')"
                  :value="dict.dictValue" />
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20" v-if="form.sqlMode!=='Y'">
          <el-col :span="24">
            <el-form-item label="Select字段" prop="columnNameArr">
              <el-select v-model="form.columnNameArr" multiple clearable placeholder="请选择要查询的字段" style="width:100%;" @change="concatSql">
                <el-option
                  v-for="dict in tableColumnOptions" :key="dict.dictValue" :label="dict.dictValue + (dict.dictLabel?('('+dict.dictLabel+')'):'')"
                  :value="dict.dictValue" />
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20" v-if="form.sqlMode!=='Y'">
          <el-col :span="24">
            <el-form-item label="Where条件" prop="filterWhere">
              <el-input v-model="form.filterWhere" placeholder="请输入过滤条件" type="textarea" :autosize="{ minRows: 2, maxRows: 4}" clearable @change="concatSql" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="24">
            <el-form-item label="查询SQL" prop="selectSql">
              <el-input
                v-model="form.selectSql" placeholder="请输入查询SQL,如果表名为空则使用SQL进行查询" type="textarea" :autosize="{ minRows: 3, maxRows: 4}"
                :disabled="form.sqlMode!=='Y'" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="24">
            <el-form-item label="是否启用" prop="isEnable">
              <el-radio-group v-model="form.isEnable">
                <el-radio v-for="dict in isEnableOptions" :key="dict.dictValue" :label="dict.dictValue">{{ dict.dictLabel }}</el-radio>
              </el-radio-group>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="归属分类" prop="cateId">
              <treeselect
                v-model="form.cateId" :options="cateOptions" :normalizer="normalizer" :loadOptions="loadOptions" :disable-branch-nodes="false"
                :show-count="false" :default-expand-level="3" placeholder="请选择归属分类" />
            </el-form-item>
          </el-col>
        </el-row>        
        <el-row :gutter="20">
          <el-col :span="24">
            <el-form-item label="备注" prop="remark">
              <el-input v-model="form.remark" placeholder="请输入备注" type="textarea" :autosize="{ minRows: 2, maxRows: 4}" clearable />
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <el-dialog v-el-drag-dialog width="780px" title="测试SQL结果" border v-model="sqlTable.open" append-to-body>
        <el-table :data="sqlTable.data">
          <el-table-column v-for="(item, index) in sqlTable.columns" :property="item" :label="item" :key="index" min-width="150px" />
        </el-table>
      </el-dialog>
      <template #footer>
        <dialog-footer @ok="submitForm" @cancel="cancel">
          <template #start>
            <el-button @click="testSql('form',form)">测试SQL</el-button>
          </template>
        </dialog-footer>
      </template>
    </el-dialog>

  </div>
</template>

<script>
import { search, insert, deleteByIds, updateById, selectById, getTableList, getColumnList, testSql } from "@data/api/data/dataset";
import { search as searchCateTree } from "@uni/api/uni/category/info";
import Treeselect from "vue3-treeselect";
import 'vue3-treeselect/dist/vue3-treeselect.css'
import { debounceWrapper } from "@/utils/zmids";
import lodash from 'lodash-es';

export default {
  name: 'DataDataSet',
  components: { Treeselect },
  data() {
    const columnLengthRule = (rule, value, callback) => {
      if (!this.form.columnName) {
        callback("表字段名不可以为空");
      } else if (this.form.columnName.length >= 1024) {
        callback("表字段名的长度最多 1024 个字符");
      } else {
        // 编辑的时候不校验
        callback();
      }
    };
    return {
      // 遮罩层
      loading: false,
      // 选中数组
      ids: [],
      // 非多个禁用
      multiple: true,
      // 显示搜索条件
      showSearch: true,
      // 总条数
      total: 0,
      // 分类
      cateOptions: [],
      // 表名列表
      tableNameOptions: [],
      // 表的字段列表
      tableColumnOptions: [],
      // 表格数据
      dataList: [],
      // 数据源列表：datasource_read
      datasourceReadOptions: [],
      // 是否启用的固定字典选项列表
      isEnableOptions: [{ "dictValue": "Y", "dictLabel": "启用" }, { "dictValue": "N", "dictLabel": "禁用" }],
      // 查询参数
      queryParams: {
        pageNum: 1,
        pageSize: 10,
        // 数据源ID
        datasourceId: undefined,
        // 数据集名称
        datasetNameLike: '',
        // 数据表名
        tableNameLike: '',
        // 是否启用
        isEnableLike: '',
      },
      // 控制 dialog
      open: false,
      // 弹出层标题
      title: '',
      // 表单参数
      form: {},
      // 规则
      rules: {
        // 数据源ID
        datasourceId: [
          { required: true, message: '数据源不可以为空', trigger: 'blur' }
        ],
        // 数据集名称
        datasetName: [
          { required: true, message: '数据集名称不可以为空', trigger: 'blur' }
          , { min: 1, max: 128, message: "数据集名称的长度最多 128 个字符", trigger: "blur" }
        ],
        // 数据表名
        tableName: [
          { required: true, message: '数据表名不可以为空', trigger: 'blur' }
          , { min: 1, max: 128, message: "数据表名的长度最多 128 个字符", trigger: "blur" }
        ],
        // 表字段名,多个以逗号隔开
        columnNameArr: [
          { required: true, validator: columnLengthRule, trigger: "blur" }
        ],
        // 过滤条件
        filterWhere: [
           { min: 1, max: 512, message: "过滤条件的长度最多 512 个字符", trigger: "blur" }
        ],
        // 是否启用
        isEnable: [
          { required: true, message: '是否启用不可以为空', trigger: 'blur' }
          , { min: 1, max: 1, message: "是否启用的长度最多 1 个字符", trigger: "blur" }
        ],
        // 分类Id
        // cateId: [
        //   { required: true, message: '归属分类不可以为空', trigger: 'blur' }
        // ],
      },
      // 测试SQL返回的数据
      sqlTable: {
        open: false,
        columns: [],
        data: [],
      },
    };
  },
  created() {
    // 查询列表
    this.getList();
    // 查询分类树
    this.getCateTreeSelect()

    // 获取数据字典：datasource_read
    this.getDicts("datasource_read").then(response => {
      this.datasourceReadOptions = response.data;
    });
  },
  methods: {
    /** 查询分类下拉树结构 */
    getCateTreeSelect: debounceWrapper(function () {
      // 只查询已经启动的分类
      searchCateTree({"cateNamespace":"data-admin", "cateLabel":"data-set"}).then(response => {
        this.cateOptions = response.data;
      });
    }),
    normalizer(node) {
      return {
        id: node.cateId,
        label: node.cateName,
        children: (node.children && node.children.length > 0) ? node.children : undefined
      };
    },    
    loadOptions(action, callback, parentNode) {
      /* empty */
    },    
    /** 选择组织节点 */
    // selectOrgNode(node) {
    //   this.form.companyId = undefined;
    //   this.form.deptId = undefined;

    //   if (node.params["type"] === 'C') {
    //     this.form.companyId = node.params["companyId"];
    //   } else if (node.params["type"] === 'D') {
    //     this.form.companyId = node.params["companyId"];
    //     this.form.deptId = node.params["deptId"];
    //   }
    // },    
    // 查询列表
    getList: debounceWrapper(function () {
      this.loading = true;
      search(this.queryParams).then(
        response => {
          this.dataList = response.data.list;
          this.total = response.data.total;
          this.loading = false;
        }
      );
    }),
    // 搜索按钮操作
    handleQuery() {
      this.queryParams.pageNum = 1;
      this.getList();
    },
    // 重置按钮操作
    resetQuery() {
      this.resetForm("queryForm");
      this.handleQuery();
    },
    // 表单重置
    reset() {
      this.form = {
        // 数据集ID
        datasetId: undefined,
        // 数据源ID
        datasourceId: '',
        // 数据集名称
        datasetName: '',
        // 自定义SQL模式
        sqlMode: 'N',
        // 数据表名
        tableName: '',
        // 表字段名,多个以逗号隔开
        columnName: '',
        // 过滤条件
        filterWhere: '',
        // 查询SQL,如果表名为空则使用SQL进行查询
        selectSql: '',
        // 是否启用
        isEnable: 'Y',
        // 备注
        remark: '',
      };
      // 重置字段校验
      this.$refs.form && this.$refs.form.clearValidate();
      this.resetForm("form");
    },
    // 多选框选中数据
    handleSelectionChange(selection) {
      // 所有选中的ID
      this.ids = selection.map(item => item.datasetId)
      // 激活多选删除
      this.multiple = !selection.length
    },
    // 新增钮操作
    handleAdd() {
      this.reset();
      this.open = true;
      this.title = "新增数据源";
    },
    // 删除按钮操作
    handleDelete: debounceWrapper(function (row) {
      const deleteIds = row ? row.datasetId : this.ids.join(",");
      deleteByIds(deleteIds)
        .then(() => {
          this.getList();
          this.msgSuccess("删除成功");
        }).catch(function () { });
    }),
    // 修改按钮操作
    handleUpdate: debounceWrapper(function (row) {
      this.reset();

      selectById(row.datasetId).then(response => {
        this.form = response.data;
        this.form.columnNameArr = this.form.columnName ? lodash.split(this.form.columnName, ",") : [];

        // 获取下拉框
        if (this.form.datasourceId) {
          getTableList(this.form.datasourceId).then(response => {
            this.tableNameOptions = response.data;
            if (this.form.tableName) {
              getColumnList(this.form.datasourceId, this.form.tableName).then(response => {
                this.tableColumnOptions = response.data;
              });
            }
          });
        }
        this.concatSql();
        this.open = true;
        this.title = "修改数据集信息表";
      });
    }),
    // 提交按钮
    submitForm: debounceWrapper(function () {
      this.form.columnName = lodash.join(this.form.columnNameArr, ',');

      this.$refs['form'].validate(valid => {
        if (valid) {
          const ifUpdate = this.form.datasetId != undefined;
          // sql模式则删除多余的数据
          if (this.form.sqlMode === 'Y') {
            this.form.tableName = '';
            this.form.columnName = '';
            this.form.filterWhere = '';
          }
          const promise = ifUpdate ? updateById(this.form) : insert(this.form);
          promise.then(response => {
            if (response.data === 1) {
              this.msgSuccess(ifUpdate ? '修改成功' : '新增成功');
              this.open = false;
              this.getList();
            }
          });
        }
      });
    }),
    // 取消按钮
    cancel() {
      this.open = false;
      this.reset();
    },
    // 选择数据源
    datasourceChange(value, option) {
      if (value) {
        getTableList(value).then(response => {
          this.tableNameOptions = response.data;
          // 如果表名存在则不重置
          var tableNameExit = false;
          this.tableNameOptions.forEach((value) => {
            if (value.dictValue === this.form.tableName) {
              tableNameExit = true;
            }
          });
          if(tableNameExit){
            this.tableNameChange(this.form.tableName);
          } else {
            this.form.tableName = '';
            this.form.columnNameArr = [];
            this.concatSql();
          }
        });
      }
    },
    // 选择表
    tableNameChange(value) {
      if (value) {
        getColumnList(this.form.datasourceId, value).then(response => {
          this.tableColumnOptions = response.data;
          var oldColumnNameArr = this.form.columnNameArr;
          this.form.columnNameArr = [];
          this.tableColumnOptions.forEach((value) => {
            oldColumnNameArr.forEach(oCol => {
              if(oCol === value.dictValue){
                this.form.columnNameArr.push(oCol);
              }
            });
          });
          this.concatSql();
        });
      }
    },
    // 组装SQL语句
    concatSql: debounceWrapper(function () {
      if (this.form.sqlMode !== 'Y') {
        this.form.columnName = lodash.join(this.form.columnNameArr, ',');
        this.form.selectSql = "SELECT " + this.form.columnName + "\r\n  FROM " + this.form.tableName + (this.form.filterWhere ? "\r\n WHERE " + this.form.filterWhere : "");
      }
    }),
    // 数据库连通性测试
    testSql: debounceWrapper(function (formRef, data) {
      this.sqlTable = {
        open: false,
        data: [],
        columns: [],
      };
      this.concatSql();
      this.$refs[formRef].validate(valid => {
        if (valid) {
          this.sqlTable.open = true;
          testSql(data).then(response => {
            if (response.data) {
              this.sqlTable.data = response.data.dataList;
              this.sqlTable.columns = response.data.columnSet;
              this.msgSuccess("获取数据成功");
            } else {
              this.msgError("获取数据失败");
            }
          });
        }
      });
    }),
  },
}
</script>

<style lang="scss" scoped>
</style>